package org.elsfs.auth.client;

import static org.assertj.core.api.Assertions.assertThat;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.elsfs.auth.entity.ResponseBody;
import org.elsfs.framework.generator.SnowFlake;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;

/**
 * 客户端模式 basic方式提交认证
 *
 * @see ClientAuthenticationMethod#CLIENT_SECRET_BASIC
 */
class CLIENT_SECRET_BASIC extends AbstractClientTypeAuthorizationServerTests {

  protected static String CLIENT_ID = "test_client_secret_basic";
  protected static String CLIENT_SECRET = "secret";
  protected static String BASIC_TOKEN =
      "Basic "
          + Base64.getEncoder()
              .encodeToString((CLIENT_ID + ":" + CLIENT_SECRET).getBytes(StandardCharsets.UTF_8));

  @Test
  @Order(10)
  public void exchange() {
    // addRegisteredClient();  profile%20openid
    RequestEntity<Void> request =
        RequestEntity.post(getUri())
            .header(HttpHeaders.AUTHORIZATION, BASIC_TOKEN)
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .build();
    ResponseEntity<ResponseBody> response = restTemplate.exchange(request, ResponseBody.class);
    LOGGER.info("{}", response);
    assertThat(response.getBody()).isNotNull();
  }

  /** 添加测试注册客户端 */
  private void addRegisteredClient() {
    RegisteredClient registeredClient =
        RegisteredClient.withId(new SnowFlake(31).nextId() + "")
            .clientId(CLIENT_ID)
            .clientSecret(passwordEncoder.encode(CLIENT_SECRET))
            .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
            .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
            .scope(OidcScopes.OPENID)
            .scope(OidcScopes.PROFILE)
            .tokenSettings(
                TokenSettings.builder().accessTokenFormat(OAuth2TokenFormat.REFERENCE).build())
            .build();
    registeredClientRepository.save(registeredClient);
  }

  /** 请求url */
  protected String getUri() {
    return new StringBuffer("http://localhost:")
        .append(this.environment.getProperty("local.server.port", "8080"))
        .append(PATH)
        .append("?")
        .append(OAuth2ParameterNames.GRANT_TYPE)
        .append("=client_credentials")
        .append("&")
        .append(OAuth2ParameterNames.CLIENT_ID)
        .append("=")
        .append(CLIENT_ID)
        .append("&")
        .append(OAuth2ParameterNames.SCOPE)
        .append("=")
        .append("profile openid") // 可选
        .append("&")
        .append(OAuth2ParameterNames.STATE)
        .append("=")
        .append("state") // 可选 任意值
        .toString();
  }
}
